package com.leisurexi.nio;

import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * {@link FileChannel} 示例
 *
 * @author: leisurexi
 * @date: 2021-01-04 17:04
 */
public class FileChannelTest {

    /**
     * 使用 FileChannel 实现文件复制
     */
    @Test
    public void test1() {
        try (
                FileChannel inChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess\\goddess.jpg"), StandardOpenOption.READ);
                FileChannel outChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess_copy.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)
        ) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            // 将 inChannel 通道中的数据读取到缓冲区中
            while (inChannel.read(buffer) != -1) {
                // 切换成读模式
                buffer.flip();
                // 写入 outChannel
                outChannel.write(buffer);
                // 清空缓冲区，便于缓冲区下次读取数据
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用内存映射的方式实现文件复制（直接操作缓冲区）
     */
    @Test
    public void test2() {
        try (
                FileChannel inChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess\\goddess.jpg"), StandardOpenOption.READ);
                FileChannel outChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess_copy2.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)
        ) {

            // 内存映射文件
            MappedByteBuffer inMappedBuf = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            MappedByteBuffer outMappedBuf = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

            // 直接对缓冲区进行数据的读写操作
            byte[] dst = new byte[inMappedBuf.limit()];
            inMappedBuf.get(dst);
            outMappedBuf.put(dst);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用 transfer 实现数据传输（直接操作缓冲区）
     */
    @Test
    public void test3() {
        try (
                FileChannel inChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess\\goddess.jpg"), StandardOpenOption.READ);
                FileChannel outChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess_copy3.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)
        ) {
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
